#include "widget3d.h"
#include <QDebug>

#define BUFFER_OFFSET(offset) ((void*) (offset))

Widget3D::Widget3D()
{
    setMinimumHeight(300);
}

Widget3D::~Widget3D()
{

}

void Widget3D::initializeGL()
{
    qInfo()<<"initializeGL";
    initializeOpenGLFunctions();

    //    glEnable(GL_TEXTURE_2D);

    m_program = new QOpenGLShaderProgram(this);

    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/triangles.vert");

    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/triangles.frag");

    m_program->link();

    //VAO，VBO数据部分
    float vertices[] = {
        //     ---- 位置 ----
        -1.0f, -1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f,  1.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 0.0f, 1.0f,
    };

    float colors[] = {
        1.0f, 1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 1.0f, 1.0f,
    };

    unsigned int indices[] = { // 注意索引从0开始!
       0, 1, 2, 3
     };

    m_posAttr = m_program->attributeLocation("aPos");
    m_colorAttr = m_program->attributeLocation("aColor");

    glGenVertexArrays(1, m_VAO);
    glGenBuffers(1, m_VBO);
    glGenBuffers(1, m_EBO);

    glBindVertexArray(m_VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER, m_VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(colors), NULL, GL_STATIC_DRAW);

    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(colors), colors);

    glVertexAttribPointer(m_posAttr, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), BUFFER_OFFSET(0));
    glVertexAttribPointer(m_colorAttr, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), BUFFER_OFFSET(sizeof(vertices)));

    glEnableVertexAttribArray(m_posAttr);
    glEnableVertexAttribArray(m_colorAttr);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Widget3D::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void Widget3D::paintGL()
{
    //    qInfo()<<"paintGL";
    glClearColor(0.2f, 0.3f, 0.3f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    m_program->bind();

    float aspect = 1.0;
    QMatrix4x4 projection_matrix;
    projection_matrix.frustum(-1.0f, 1.0f, -aspect, aspect, 1.0f, 500.0f);
    m_program->setUniformValue("projection_matrix", projection_matrix);

    glBindVertexArray(m_VAO[0]);

    QMatrix4x4 model_matrix;
    model_matrix.translate(-3.0f, 0.0f, -5.0f);
    m_program->setUniformValue("model_matrix", model_matrix);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    QMatrix4x4 model_matrix2;
    model_matrix2.translate(-1.0f, 0.0f, -5.0f);
    m_program->setUniformValue("model_matrix", model_matrix2);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);

    QMatrix4x4 model_matrix3;
    model_matrix3.translate(1.0f, 0.0f, -5.0f);
    m_program->setUniformValue("model_matrix", model_matrix3);
    glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0, 1);

    QMatrix4x4 model_matrix4;
    model_matrix4.translate(3.0f, 0.0f, -5.0f);
    m_program->setUniformValue("model_matrix", model_matrix4);
    glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1);

    m_program->release();
}
